/** @jsxImportSource @emotion/react */
import * as React from "react";
import {
    useTheme,
    Button,
    useToast,
    Text, Spinner,
    IconButton,
    IconArrowLeft,
    TwoHalfRightPanel,
    useMMenuBarOcup,
    VerticalMenu,
    DdMenuItem, DdMenu, TableRow, CCell,
} from "customize-easy-ui-component";
import { InternalItemHandResult, OriginalViewProps, } from "./common/base";
import { Link as RouterLink } from "../routing/Link";
import { EditStorageContext } from "./StorageContext";
import { TransparentInput } from "../comp/base";
import { useThrottle } from "../hooks/useHelpers";
import useOriginalDataMutation from "./useOriginalDataMutation";
import useFlowToMutation from "./useFlowToMutation";
import { useContext} from "react";
import RoutingContext from "../routing/RoutingContext";
import {RefetchFnDynamic} from "react-relay/relay-hooks/useRefetchableFragmentNode";
import { Global } from "@emotion/react";
import cutting_board_knife from "../images/cutting-board-knife.jpg";
import {useMeasure} from "customize-easy-ui-component/esm/Hooks/use-measure";
// import {TwoHalfRightPanel} from "../comp/TwoHalfRightPanel";


/*
【用处】 真正原始记录的编辑器开始入口点。底下的template && React.cloneElement(template as实际对应了modelConfigs.ts文件指出PeriodicalInspection.E.tsx的组件，
    也就是最后的 originalTemplate={<OriginalView inp={null} 之对应的<OriginalView 。
错误！ 本地重复定义了外部全局实例，结果本文件内只能看到 自己的EditStorageContext，而不是公用的哪一个。
export const EditStorageContext = React.createContext<EditStorageContextType | null>(
  null
);
*/


//必须通过prepared:{内嵌}传递，因为 路由器给出上一级组件 实际上中间还嵌入一层<RouteComponent/>的，所以算是非直接儿子的传递参数。
interface RecordStarterProps {
    prepared: {
        //数据
        source: any;
        //原始记录的模板：
        template: React.ReactElement<React.ForwardRefRenderFunction<InternalItemHandResult,OriginalViewProps>>;
    }
    routeData: any;
    children: React.ReactNode;
    ispId: string;
    refetch: RefetchFnDynamic<any, any>;
    noHalfFrame?: boolean;
    /**报告的对象，还是需要给编辑器的*/
    rep: any;
}
//是 右边半边页面的！，编辑，或原始记录的查看：
export const RecordStarter: React.FunctionComponent<RecordStarterProps> = ({
    rep,
    ispId,
    refetch,
    routeData,
    prepared:{source, template, ...other2},
    children,
    noHalfFrame,
    ...other
 }) => {
    // console.log("RecordStarter捕获,切花个other2=", other2,"other=",other,"children",children);
  const theme = useTheme();
  const toast = useToast();
  //初始化不可以直接取React.useState(source || {})，不然路由器切换就变成旧source。新修改被抛弃了。
  const context =React.useContext(EditStorageContext);
    if(context == null)    throw new Error("EditStorageContext没有提供");
    const {storage, setStorage, modified,setModified, } =context;

    const { history } = useContext(RoutingContext);
    console.log("右RecordStarter捕获,切source=", source,"routeData=",routeData,"storage",storage);
    const onSaved = React.useCallback(
        (e:any) => {
            setModified(false);
        },
        [setModified]
    );
    const {call:updateFunc,doing,result, called, reset}= useOriginalDataMutation(onSaved);
    const {call:flowToFunc,doing:flowing, called:flowed, reset:flowreset}= useFlowToMutation();
  //console.log("RecordView捕获,切花source=", source,"新storage=",storage);

  async function updateRecipe(
    id: string ) {
    let yes= result && result.id;
    try {
      //提交给后端， 这里将会引起底层变动，导致本组件即将要render3次。有更新的4次。更新比读取多了1次render。
        const { _version, ...RepData }= (storage || source);
        await updateFunc(id, 1, JSON.stringify(RepData) , `{emergencyElectric:'45,423'}`,_version);
    } catch (err: any) {
      toast({
        title: "后端请求错",
        subtitle: err.message,
        intent: "error"
      });
      //很多错误是在这里捕获的。
      console.log("updateRecipe返回了,捕获err", err);
      return;
    }
    //这里无法获得result值，就算所在组件顶层已经获得result值，这里可能还是await () 前那样null;
    console.log("保存返回了＝", result,"yes=", yes);
    //除非用const {data: { buildTask: some }} = await updateFunc()捕捉当前操作结果; 否则这时这地方只能用旧的result,点击函数里获取不到最新结果。
    //须用其它机制，切换界面setXXX(标记),result？():();设置新的URL转场页面, 结果要在点击函数外面/组件顶层获得；组件根据操作结果切换页面/链接。
  }


  //const [throttledUpdateBackend, timer1]= useThrottle(updateRecipe,0);
  //延迟3秒才执行的; 可限制频繁操作，若很多下点击的3秒后触发2次。
  //【注意】延迟时间设置后，页面切换会报错，组件已经卸载，还来setEnable啊，状态错误！
  const {doFunc:throttledUpdateRecipe, ready} = useThrottle(updateRecipe,5000);
  const refEditor =React.useRef<InternalItemHandResult>(null);
  const {doFunc:throttleDoConfirm, ready:confirmEnable} =useThrottle((refEditor as any)?.current?.doConfirm);
  //const [throttledUpdateEnable, isReady] = useThrottle(setEnable, 5000);
  /*
  React.useEffect(() => {
    return () => {
      clearTimeout(timer2);
    };
  }, [timer2]);
  */
  //可是这里return ；将会导致子孙组件都会umount!! 等于重新加载==路由模式刷新一样； 得权衡利弊。
  // if(updating)  return <LayerLoading loading={updating} label={'正在获取后端应答，加载中请稍后'}/>;
  //管道单线图，数量大，图像文件。可仅选定URL，预览图像。但是不全部显示出来，微缩摘要图模式，点击了才你能显示大的原图。
  /*
  async function toSaveBackEnd() {
      //手机上更新模板TemplateView子组件重做render触发失效。只好采用延迟策略，每个分区项目的保存处理前准备，作一次render完了，才能发送数据给后端。
      setEnable(false);
      await updateRecipe('1');    //阻塞了await关键字只能用在aync定义的函数内。

    throttledUpdateEnable(true);
  }
*/
    const refHolw = React.useRef<HTMLDivElement>(null);
    // const yHolw= useMeasure(refHolw.current? refHolw : null);

    const { carousel } = useMMenuBarOcup(false);
    const curFlow=sessionStorage['审批单']&&JSON.parse(sessionStorage['审批单']);
    const curUrl= history.createHref(history.location);
    const timerRef = React.useRef(null as any);

    if (!routeData.params.repId) {
    return null;
    }
    //【流转审批看得URL】
    const hrefR =`/reportView/EL-DJ/ver/1/${routeData.params.repId}?&print=1`;
    // console.log(`撞见该是却也显示了可达：`, yHolw?.width, "浏览器宽度",window.outerWidth);
    const newPrintWindow=(width: number)=>{
        //【完全动态网页的打印办法】必须开启时就是纸张大小的窗口，避免后面几张无法打印；该容器中页面视图区的宽度（减去边框） window.innerWidth=718; CDP:Browser.setWindowBounds
        let newPrWindow=window.open(curUrl, "_blank","popup");
        newPrWindow!.opener = null;
        newPrWindow!.resizeTo(width,window.outerHeight);      //打印预定A4纸张大小。
    };
  //无法把<EditStorageContext.Provider value={{storage,setStorage}}>放这附近能产生效果，必须提升到顶级路由组件内去做。
  return (
    <React.Fragment>
        <Global
            styles={{
                html: {
                    [theme.mediaQueries.md]: {
                        backgroundAttachment: "fixed",
                        backgroundSize: "cover",
                        backgroundImage: `url(${cutting_board_knife})`
                    }
                }
            }}
        />
       <Global
          styles={{
              html: {
                  "@page": {
                      // size: 'A4 portrait',  //'A4 landscape',
                  },
                  "#root #floormenu": {
                      // display: 'none',
                      opacity: modified? '0.3' : 'unset',
                  }
              }
          }}
       />

      <TwoHalfRightPanel  noHalfFrame={noHalfFrame}
          title={
              (routeData.params.action==='ALL'|| routeData.params.action==='printAll') ?
                  <div css={{ marginLeft: "-0.75rem", flex: 1 }}>
                      <TransparentInput
                          autoComplete="off"
                          autoFocus
                          inputSize="md"
                          value={routeData.params.action}
                          placeholder="报告的详细可打印信息"
                          aria-label="Recipe title"
                          onChange={e => {
                          }}
                      />
                  </div>
                 :
                  <Text
                      css={{
                          flex: 1,
                          textAlign: "center",
                          "@media (min-width:800px)": {
                              textAlign: "left"
                          }
                      }}
                      wrap={false}
                      variant="h5"
                      gutter={false}
                  >
                      报告ID：{routeData.params.repId}
                  </Text>
          }
          back={
              <RouterLink  href={`/report/${routeData.params.template}/ver/${routeData.params.verId}/${routeData.params.repId}`}>
                  <IconButton  noBind
                               icon={<IconArrowLeft />}
                               label="后退"
                               variant="ghost"
                               css={{
                                   marginRight: theme.spaces.sm,
                                   "@media (min-width:800px)": {
                                       display: "none"
                                   }
                               }}
                  />
              </RouterLink>
          }
          menu={
              <VerticalMenu>
                  <DdMenu label="其余操作">
                      <DdMenuItem label="刷新报告数据"
                                  onClick={ async () => {
                                      await refetch({},{fetchPolicy: "network-only"});
                                      // history.replace(myUrl, {time: Date()} );
                                  } }
                      />
                      <DdMenuItem label="简易版原始记录" onClick={async () => {
                          const lzurl=`/originalView/${routeData.params.template}/ver/${routeData.params.verId}/${routeData.params.repId}/printAll`;
                          await history.push(lzurl, {});
                      }} />
                  </DdMenu>
                  <DdMenuItem label="保存到服务器" disabled={!ready} onClick={(e) => {
                      throttledUpdateRecipe!(routeData.params.repId)
                  }} />
                  <DdMenuItem label="全部项目一起确认" disabled={!confirmEnable} onClick={(e) => {
                      if(throttleDoConfirm)  throttleDoConfirm(true);
                      else (refEditor as any).current!.doConfirm(true);
                  }} />
                  <DdMenuItem label="检验员签字转入流转主页(流程)" disabled={ !(curFlow?.entId===routeData.params.repId) } onClick={(e) => {
                      flowToFunc( curFlow?.utId , routeData.params.repId,3,hrefR,'测ok2');
                      toast({title: "报告签字完成"});
                      //签字成功与否，都将可直接清空session状态; 不支持并发进行多个审批单子或多份报告同时进入审核工作范围。一个时间点只能一条审批事项。
                      sessionStorage['审批单'] =null;
                  }} />
                  <DdMenuItem label="流转(流程)" onClick={async () => {
                      const lzurl=`/report/${routeData.params.template}/ver/${routeData.params.verId}/${routeData.params.repId}/flowSelect`;
                      await history.push(lzurl, {});
                  }} />
                  <DdMenuItem label="正式报告"
                         onClick={()=> history.push(`/reportView/${routeData.params.template}/ver/${routeData.params.verId}/${routeData.params.repId}?print=1`)
                    } />
              </VerticalMenu>
          }
          css={{
              "@media print": {
                  display: "none"
              }
          }}
      >
          <div ref={refHolw}>
              <div  css={{
                "@media not print": {
                  display: "none"
                }
              }}>
                <Text variant="h4" css={{textAlign:'center'}}>福建省特种设备检验研究院</Text>
                 <Text>
                 本原始记录对应的报告模板类型：{routeData.params.template}，版本：{routeData.params.verId}，报告ID：{routeData.params.repId}
                 </Text>
                <hr/>
              </div>
              {
                //【原始记录模板的挂接起始点】OriginalView的上级；useMemo使用后：各分区项目子组件inp各自独立的，分区项目子组件内若使用setInp(null) 清空重置后，无法靠重新拉取后端数据来保证恢复显示。
                //项目子组件使用setInp(null) 重置后，若上级组件重新取后端数据没变化的，也必须再次路由后再进入才可以让各分区项目子组件render恢复显示数据。
                //这里refEditor仅在框架上点击确认保存时刻才有用到；template就是右边页面=模板的起点组件{实际可以只有单个区域项目编辑器也可能ALL全部编辑项目列表}。.useImperativeHandle( ref,() => ({doConfirm: setDoConfirmModify }),被触发。

                  source?  template && React.cloneElement(template as React.ReactElement<any>, {
                      ref: refEditor,
                      inp: source,
                      action: routeData.params.action,
                      repId: routeData.params.repId,
                      rep,
                    })
                 :
                <>稍后，后端还没有给数据！</>
              }
             {/*确认修改按钮，需要每个当前检验项目的编辑器inp，所以无法提升到这个层次做触发*/}
              <div css={{
                  display: 'flex',
                  alignItems: 'center',
                  justifyContent: 'space-evenly',
              }}>
                  <Button
                      css={{ marginTop: theme.spaces.md }}
                      size="lg"  intent={'warning'}
                      disabled ={!ready}
                      onPress={ ()=>{throttledUpdateRecipe!(routeData.params.repId);
                      } }
                  >保存到服务器</Button>
                  <DdMenu label="原生打印" tight={true}
                          icon={<Button css={{ marginTop: theme.spaces.md }}>原生打印</Button>}
                  >
                      <DdMenuItem label={'竖屏A4窗口'}
                                  onClick={(e) => {
                                      //撞见该是却也显示了可达： 718 浏览器宽度 751  console.log(`撞见该是却也显示了可达：`, yHolw?.width, "浏览器宽度",window.outerWidth);
                                      //【决定数值办法】调整浏览器宽度，看打印日志。一直到：打印和不打印的2个render最后的yHolw?.width取数一样；对应的览器宽度 751=就是底下要配置目标宽度。
                                      newPrintWindow(751);
                                  }}/>
                      <DdMenuItem label="横屏A4窗口"
                                  onClick={async(e) => {
                                      newPrintWindow(1080);
                                  }}/>
                      <DdMenuItem label="最后才打印"
                                  onClick={(e) => {
                                      clearTimeout(timerRef.current);        //若没加定时器的直接打印会把当前弹出的菜单项列表一起显示出来的。
                                      timerRef.current = setTimeout(() => {
                                          window.print();        //不能直接用newPrWindow!.print(); 不是同一个APP环境的;
                                      }, 500);
                                  }}/>
                  </DdMenu>
                  <RouterLink href={`/inspect/${ispId}`}>
                      返回本次检验
                  </RouterLink>
              </div>
              <Spinner doing={doing} carousel={carousel}/>
        </div>
      </TwoHalfRightPanel>
    </React.Fragment>
  );
}


export default RecordStarter;


/* Chrome浏览器打印：早早就定死了输出的纸张数；完全动态页面可能出现漏打或空白页；目前解决方案是约定浏览器宽度后做打印。CDP也会有类似问题。
【动态内容遇到的打印不全问题】末尾插入方式“只能支持页面启动就明确打印页数的才有效；用副作用中间纯动态变更的就不行了，打印页数早就被限制死了，后面无法再改了。
    const [vtpage, setVtpage] = React.useState(Math.ceil((yBdv0?.top!-yHolw?.bottom!)/yHolw?.width!) || 0);
    React.useEffect(() => {
        if((yBdv0?.top!-yHolw?.bottom!)>0 && (yHolw?.width!)<yBdv0?.width! && (yHolw?.bottom!)>0)
        {
            console.log(`撞见该是却也显示了情形：`, yHolw,"虚拟断开",yBdv0, "系数有=", (yBdv0?.top!-yHolw?.bottom!)/yHolw?.width!);
            //没处理【报错】Too many re-renders. React limits the number of renders to prevent an infinite loop.
            setVtpage(Math.ceil((yBdv0?.top!-yHolw?.bottom!)/yHolw?.width!) || 0);
        }
    }, [yBdv0, yHolw, setVtpage]);
return <div ref={refBdv0} css={{"@media print": {pageBreakBefore:'always'}}}/>
          { (new Array(vtpage)).fill(null).map((_, i:number) => {
              console.log(`该是却也显示了情形加虚拟纸张数=`, vtpage,"断页i=",i);
              return <div key={i} css={{"@media print": {pageBreakBefore:'always'}}}/>;
          }) }
* */
